// in server1.js
var http = require("http"); // reference: Node.js HTTP Module
var server = http.createServer((request, response) => {
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("<h1>Hello World!</h1>");
response.end();
});
server.listen(8080); // Use your port number instead of 8080.
How to run? $ node server1.js in the command-line interfacehttp://cs.tru.ca:8080 or http://198.162.21.132:8080 on a web browser, not https.
What do you see? Big 'Hello Wrold!'?
require() do?.listen() do?.createServer()?request and response, are passed.
request holds all the information related to the HTTP request sent from a client, and
response is used to send data back to the client.request, Node.js IncomingMessage Object
For more information about response, Node.js HTTP ServerResponse Object
exportsserver2.js into a module?
// server2.js
var PORT_NO = 8080; // Use your port number, not 8080
var http = require('http');
function start() {
var server = http.createServer(
(request, response) => { // request: from the client; response: to the client
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("<h1>Hello World!</h1>");
response.end();
}
);
server.listen(PORT_NO);
}
// Something more
exports.start = start;
index2.js?
// index.2.js
var server = require('./server2'); // server2.js; the variable server represents all the exported functions in server2.js
server.start(); // .start() is the function that is defined in server2.js and exported.
$ node ./index2
request and response to Router?router3.js
function route(request, response) {
response.writeHead(200, {'Content-Type': 'text/plain'}); // Plain text, not html text, will be sent back to the client
response.write("<h1>Hello World!</h1>");
response.end();
}
exports.route = route;
index3.js, and pass it to the server.index3.js
var server = require('./server3');
var router = require('./router3');
server.start(router);
server3.js
var PORT_NO = 8080; // Use your port number, not 8080
var http = require('http');
function start(router) { // Do we have to require 'router'?
var server = http.createServer(
(request, response) => { // request: from the client; response: to the client
router.route(request, response);
}
);
server.listen(PORT_NO);
}
// Something more
exports.start = start;

var server = require('./server');
var router = require('./router');
server.start(router);
var PORT_NO = 8080; // Use your port number
var http = require('http');
function start(router) {
var server = http.createServer(
(request, response) => { // request: from the client; response: to the client
router.route(request, response);
}
);
server.listen(PORT_NO);
}
// Something more
exports.start = start;
function route(request, response) {
response.writeHead(200, {'Content-Type': 'text/plain'}); // Plain text, not html text, will be sent back to the client
response.write("<h1>Hello World!</h1>");
response.end();
}
exports.route = route;
request?
(Note that pathname obtained from url.parse(request.url).pathname starts with '/'.)
var url = require("url"); // reference: Node.js URL Module
function route(request, response) {
var pathname = decodeURI(url.parse(request.url).pathname); // decodeURI(): a JS built-in function
// reference: JavaScript decodeURI()
response.writeHead(200, {"Content-Type": "text/html"}); // text/html, not text/plain, in this example
response.write("<h1>Hello World!</h1><br>");
response.write(pathname + "<br>");
response.end();
}
exports.route = route;
"tilde-expansion" module.
After you install the module as $ npm install tilde-expansion in the current working directory,
var tilde = require("tilde-expansion"); // reference: tilde-expansion
tilde(username, function(expanded) { // E.g., "~tom" -> "/home/students/tom"
console.log(expanded);
});
request.url.request.url..sjs files.
.sjs files..sjs files..sjs files:
proceed() should be exported.
This function is the starting point in a server-side JS program, like main() in Java.
// In each .sjs file,
// _GET: object for the GET data
// _POST: object for the POST data
// callback: callback function to pass a message back to the client
const proceed = function(_GET, _POST, callback) {
...
}
exports.proceed = proceed;
proceed(), the callback function should be used to send any message back to the client.
.proceed() will be invoked to execuse them.
The return message from .proceed() will be sent back to the client.
proceed(),
in which the application code is fully responsible how to use request.url and how to send messages or data back to the client.
const proceed = function(request, response) {
...
}
exports.proceed = proceed;
request.url?
var url = require('url'); // reference: Node.js URL Module
function route(request, response)
{
var pathname = decodeURI(url.parse(request.url).pathname); // encodeURI(), decodeURI()
// What does decodeURI() do?
...
}
$ npm install tilde-expansion
var tilde = require('tilde-expansion'); // reference: tilde-expansion
var words = pathname.split('/'); // words[0] is '' and words[1] is '~...' because pathname starts with '/'. E.g, /~tom/...
if (words[1] != undefined && words[???][???] == '~') // e.g., pathname is /~tom/...
tilde(words[1], function(expanded) {
var new_pathname = expanded + '/???'; // 'public_html' should be included.
for (var i = 2; i < words.length; i++)
new_pathname += '/' + ???;
});
else
var new_pathname = "/var/www/html" + pathname;
var url = require('url');
function route(request, response)
{
var pathname = decodeURI(url.parse(request.url).pathname);
var tilde = require('tilde-expansion');
var words = pathname.split('/'); // words[0] is '' and words[1] is '~...' because pathname starts with '/'.
// Case 1
if (words[???] != undefined && words[???][???] == '~') { // e.g., /~tom/... => '', '~tom', ...
tilde(words[1], function(expanded) { // Note that a callback function is used.
var new_pathname = expanded + '/???'; // 'public_html' should be included.
for (var i = 2; i < words.length; i++)
new_pathname += '/' + ???;
????
});
???? // really necessary?
}
// Case 2
else {
var new_pathname = "/var/www/html" + pathname;
????
}
}
function proceed_with_resolved_pathname (req, res, pathname) {
???? // send the pathname to the client
}
if (pathname.endsWith("/")) {
pathname = pathname + "/index.html";
...
}
var url = require('url');
function route(request, response)
{
var pathname = decodeURI(url.parse(request.url).pathname);
var tilde = require('tilde-expansion');
var words = pathname.split('/'); // words[0] is '' and words[1] is '~...' because pathname starts with '/'.
// Case 1
if (words[1] != undefined && words[1][0] == '~') { // e.g., /~tom/...
tilde(words[1], function(expanded) { // Note that a callback function is used.
var new_pathname = expanded + '/???'; // 'public_html' should be included.
for (var i = 2; i < words.length; i++)
new_pathname += '/' + words[i];
proceed_with_resolved_pathname(request, response, new_pathname);
});
}
// Case 2
else {
var new_pathname = "/var/www/html" + pathname;
proceed_with_resolved_pathname(request, response, new_pathname);
}
}
function proceed_with_resolved_pathname(req, res, pathname)
{
// Case 3
???? // what if pathname ends with '/'?
res.writeHead(200, {"Content-Type": "text/html"}); // text/html, not text/plain, in this example
res.write("<h1>Hello World!</h1><br>");
res.write(??? + "<br>");
res.end();
}
const path = require("path"); // reference: Node.js Path Module
let fileordirname = path.basename(pathname);
let words = fileordirname.split(".");
if (words.length > 1) {
let extension = words[words.length - 1];
...
} else {
...
}
const path = require("path");
let fileordirname = path.basename(pathname);
let words = fileordirname.split(".");
let extension;
if (words.length > 1) {
extension = words[words.length - 1];
} else {
pathname = ????
extension = ????
}
...
var url = require('url');
function route(request, response)
{
var pathname = decodeURI(url.parse(request.url).pathname);
var tilde = require('tilde-expansion');
var words = pathname.split('/'); // words[0] is '' and words[1] is '~...' because pathname starts with '/'.
// Case 1
if (words[1] != undefined && words[1][0] == '~') { // e.g., /~tom/...
tilde(words[1], function(expanded) { // Note that a callback function is used.
var new_pathname = expanded + '/???'; // 'public_html' should be included.
for (var i = 2; i < words.length; i++)
new_pathname += '/' + words[i];
proceed_with_resolved_pathname(request, response, new_pathname);
});
}
// Case 2
else {
var new_pathname = "/var/www/html" + pathname;
proceed_with_resolved_pathname(request, response, new_pathname);
}
}
????
function proceed_with_resolved_pathname(req, res, pathname)
{
// Case 3
if (pathname.endsWith("/"))
pathname = pathname + "/index.html";
// Case 4
????
res.writeHead(200, {"Content-Type": "text/html"}); // text/html, not text/plain, in this example
res.write("<h1>Hello World!</h1><br>");
res.write(??? + "<br>");
res.write("Extension: " + ??? + "<br>");
res.end();
}
<HTML>
<HEAD>
<meta HTTP-EQUIV="REFRESH" content="0; url=http://www.tru.ca:80/science/programs/compsci.html">
</HEAD>
</HTML>
response.writeHead(301, {'Location': different_location});
var fs = require('fs');
var filename = 'test.html';
fs.readFile(filename, 'utf8', function(err, content) {
if (!err) {
console.log(content);
}
else {
console.log(err);
}
});
router.js.
if (extension != 'sjs' && extension != 'php') {
var fs = require('fs'); // reference: Node.js File System Module
if (extension == 'html' || extension == 'htm')
content_type = 'text/html';
else if ...
...
fs.readFile(pathname, 'utf8', function(err, content) {
if (!err) {
response.writeHead(200, {'Content-type': content_type}); // 200: OK; important
response.write(content);
response.end();
}
else {
response.writeHead(404, {'Content-type': "text/html"}); // 4xx: client error
response.end("<html><body><h1>Not Found</h1><p>The requested URL was not found on this server.</p><hr></body></html>");
}
});
}
// A server-side JavaScript file, e.g., echo_server.sjs and calculator_server.sjs:
// _GET: object for the GET data
// _POST: object for the POST data
// callback: callback function to pass a message back to the client
function proceed(_GET, _POST, callback) {
...
}
exports.proceed = proceed;
.sjs?
if (extension == 'sjs') {
if (request.method.toLowerCase() == "get") {
...
}
else if (request.???? == '???') {
...
}
...
}
'http://test.com/start.html?command=Login&username=foo&password=topsecret'.decodeURI(url.parse(request.url).pathname) → '/start.html'decodeURI(url.parse(request.url).query) → 'command=Login&username=foor&password=topsecret'var _GET = querystring.parse(decodeURI(url.parse(request.url).query)) → { command:'Login', username:'foo', password:'topsecret' }_GET['command'] → 'Login'JSON.stringfy()request' is an Event Emitter object, and
it will emit the 'data' event whenever the incoming POST data is received.
When there is no more incoming POST data, the 'end' event is emitted..on() method on 'request' can used to listen to these events.
var query = '';
var _POST = {};
request.on('data', function(chunk) { // request is an Event Emitter.
query += chunk;
});
request.???('end', function() { // the end of the data
if (query != '')
_POST = ???? // parsing using the 'querystring' module. Check the example in the above 'GET' case.
});
_POST.
//---- TRUWSJS ----
var sjs = ???(pathname); // 'pathname' is a sjs script file. This file is required as a module. For example, test.sjs.
// We assume that all '.sjs' programs have the function, proceed(),
// that is the starting point like main() in Java and C/C++ programs.
// _GET: object for the GET query; _POST: object for the POST query
// For example, { command:'Login', username:'foo', password:'topsecret' }
sjs.proceed(_GET, _POST, function(content) { // callback function to get the result from the sjs program
....
response.???("" + content);
response.???();
});
//---- test.sjs ----
function proceed(_GET, _POST, callback) {
var content;
if (_GET['command'] == 'Login') // For example
...
....
???(content); // Don't forget that this function should pass a message back through callback
}
???.??? = proceed;
try-catch?throw?isNaN() do?
var divide = function(x, y) {
if (y === 0)
// throw new Error({name: 'Divide', message: "Can't divide by zero"}); // or
throw {name: 'Divide', message: "Can't divide by zero"};
else
return x/y;
};
try {
var result = divide(4, 2);
...
}
??? (e) {
console.log(e.???); // Not just e. e.name, e.stack, e.message, ...
}
??? {
var sjs = require(pathname); // We assume all '.sjs' programs have proceed().
sjs.proceed(_GET, _POST, function(html_content) {
....
});
} ??? (err) {
....
}
??? {
var sjs = require(pathname); // We assume all '.sjs' programs have proceed().
var ended = false;
sjs.proceed(_GET, _POST, function(html_content) {
if (!ended) {
.... // write(), ..., end()
delete require.cache[require.resolve(pathname)]; // in order to unload this .sjs module;
// https://nodejs.org/api/modules.html#requirecache
ended = true; // when the callback function is invoked multiple times from the sjs app,
// response.end() is invoked again.
// It causes an error that cannot be caught.
}
});
} catch (err) {
....
???[???]; // in order to unload this .sjs module
}
var https = require('https');
var fs = require('fs');
var options = {
key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'), // Key
cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem') // Certificate
};
https.???(options, function (req, res) { // similar to http
res.writeHead(200);
res.end("Hello world!\n");
}).???(8443);
var https = require('https'),
pem = require('pem');
pem.createCertificate({days:100, selfSigned:true}, function(err, keys) {
if (!err)
https.???({key: keys.serviceKey, cert: keys.certificate}, function(req, res) {
res.writeHead(200);
res.end("Hello world!\n")
}).???(8443);
});
var http = require('http');
var https = require('https');
var pem = require('pem');
//var ws_server = require('./ws_server');
function start(route)
{
// HTTP server
var server = http.???(function(request, response) {
route(request, response);
});
server.???(8080);
// WebSocket server integrated with HTTP server
// It will be discussed later.
//ws_server.start(server); // WebSocket server: ws Node.js module
// HTTPS server
pem.createCertificate({days:100, selfSigned:true}, function(err, keys) {
if (!err)
https.???({key: keys.serviceKey, cert: keys.certificate}, function(request, response) {
???(???, ???);
}).???(8443);
});
}
???.start = start;